fix(phi-scan): a target enumerated and never read refuses the scan - #113
Merged
Conversation
…arden the control
…runs The headline case's comment claimed `config`'s capability probe measured its drift on that argv. It does not: the probe's graded run is `[violator, decoy, --allow-fixture decoy]`, whose pre-rule result is the HITS code (1), and the headline case's pre-rule result is exit 0. One run cannot have produced both, so the comment marked the wrong test as the externally graded one. Comment only; no assertion, fixture or scanner behaviour changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
--allow-fixturewithdrew a path from the target list and the run reported on whatever remained, so the withdrawal never showed up in the verdict. Four argv shapes printed[phi-scan] OK, no hitsat exit 0 over a corpus holding a live, detectable violator:phi-scan <clean> --allow-fixture <violator>paths.length > 0 ? paths : [...allowFixtures], so with a positional present the flag was a silent no-op and the violator was never ADMITTED to the run rather than withdrawn from itphi-scan <violator> --allow-fixture <violator>phi-scan --allow-fixture <violator>phi-scan --staged --allow-fixture <violator>In every one of them the file was validated, checked against the override log, and opened never. CI could print a clean verdict over a corpus it never opened.
What changed
A target this run enumerated and never read refuses (exit 2), in every mode, naming the paths. The comparison is a set difference, never a size: a count counts the targets that did get read, which is exactly the arithmetic that hides which ones did not.
A second tier refuses a bypass naming a path the run does not enumerate, under its own message, because such a flag subtracts nothing.
--allow-fixtureno longer selects the mode, and inpathsmode it is unconditionally unioned into the target list (deduped by repo-relative path) so it means the same thing in every argv.Hits are printed before the post-sweep refusals, so a run that is both incomplete and carrying hits prints both.
What it costs, stated rather than left to be discovered
--allow-fixturecan no longer reach exit 0 in any mode. The flag,phi-scan-overrides.mdand the log gate all stay, so an attempt is recorded and then REFUSED rather than silently honored, andscripts/phi-allow-list.txtis now the only mechanism that reaches a clean run. The hit footer no longer advertises the flag: a printed remedy that walks a developer from exit 1 into exit 2 is the same defect as one that reaches a false green, with the sign flipped.The vanish tolerance (
Target.tolerateVanish) is the one accounted-for non-read and is subtracted from the difference, or theccda@0.0.5publish-time refusal comes straight back. It cannot launder a bypass: a bypassed path is skipped beforescanTargetis ever called, so it can never enter the vanished set.The null result
There was no real unread corpus here. Measured at
1978bf7, all-mode enumerates 141 paths and reads all 141, nothing tolerated, nothing unread. The figures are dated to that commit rather than asserted as current, because the.changeset/entry shipping this raises the tracked figure by one until a release consumes it. That 141 is not the tracked count wearing a different hat: 141 tracked, minus the one declared literal exclusion, is 140 in-scope tracked paths, plus the.gitgitfile a submodule checkout carries in place of a directory (a pre-existing, already-filed observation). The four states were reproduced with planted fixtures, not found.ncpdpreached the same null result on the union half.The positive control
Nine new cases. The last one runs the same argv against a copy of the scanner with the rule's one line mutated out, asserts the mutation landed (so it cannot go vacuous when the rule is reworded), and asserts the mutant reproduces both pre-fix results exactly: the HITS code where the corpus still holds a readable violator, and
OK, no hitsat exit 0 where it does not. Run against the pre-change scanner, seven of the nine red; the two that pass are the anti-vacuity premise and the no-false-refusal case, which must hold on both trees.Every assertion pins an exact exit code and the message naming which of the three exit-2 tiers fired. This repo shipped
expect(merged.status).not.toBe(0)passing on agit mergethat died at exit 128 on a committer identity before it touched the index (#111): a premise assertion that accepts any non-zero exit accepts a crash.Verification
scripts/verify.sh ccda: green.cd config && pnpm drift: thephi-scan completeness probedrift forccdais gone. Before:phi-scan reported only its HITS code (1) over a run that withdrew test/fixtures/phi-scan-probe-decoy.txt after enumerating it. After: no completeness line.No published API, warning code or parser behaviour changes; this is the commit gate only.